package xyz.bmj.hotkey;

import lombok.Getter;
import lombok.Setter;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

public class HotKey {
    private static final Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());

    @Getter
    private final Map<Cbk, Runnable> cb = new HashMap<>();
    @Setter
    private pressListener press;

    public void removePress() {
        press = null;
    }

    private static class Instance {
        private static final HotKey instance = new HotKey();
    }

    public static HotKey getInstance() {
        return Instance.instance;
    }

    private HotKey() {
        logger.setLevel(Level.OFF);
        try {
            GlobalScreen.registerNativeHook();
        } catch (NativeHookException ex) {
            ex.printStackTrace();
        }
        GlobalScreen.addNativeKeyListener(new NativeKeyListener() {
            @Override
            public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) {

            }

            @Override
            public void nativeKeyPressed(NativeKeyEvent nativeKeyEvent) {
                if (press != null) {
                    press.run(nativeKeyEvent);
                }
                doKey(nativeKeyEvent);
                //System.out.println(nativeKeyEvent.paramString());
            }

            @Override
            public void nativeKeyReleased(NativeKeyEvent nativeKeyEvent) {
            }
        });
    }

    private void doKey(NativeKeyEvent nativeKeyEvent) {
        Set<Cbk> ks = cb.keySet();
        for (Cbk cbk : ks) {
            if (checkKeys(cbk, nativeKeyEvent)) {
                cb.get(cbk).run();
            }
        }
    }

    private boolean checkKeys(Cbk cbk, NativeKeyEvent nativeKeyEvent) {
        if (cbk.markKey == nativeKeyEvent.getModifiers()) {
            return cbk.masterKey == nativeKeyEvent.getKeyCode();
        }
        return false;
    }


    public void setKey(Runnable runnable, int masterKey, int marks) {
        Cbk cbk = new Cbk();
        cbk.masterKey = masterKey;
        cbk.markKey = marks;
        cb.put(cbk, runnable);
    }

    public void clear() {
        cb.clear();
    }

    public interface pressListener {
        void run(NativeKeyEvent nativeKeyEvent);
    }
}
